home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / emula / arosdv19.lha / AROS / intuition / frameiclass.c < prev    next >
C/C++ Source or Header  |  1996-10-29  |  12KB  |  507 lines

  1. /* AROS frameiclass implementation
  2.  * 10/24/96 caldi@usa.nai.net
  3.  */
  4.  
  5. #include <exec/types.h>
  6.  
  7. #include <dos/dos.h>
  8. #include <dos/dosextens.h>
  9.  
  10. #include <intuition/intuition.h>
  11. #include <intuition/intuitionbase.h>
  12. #include <intuition/classes.h>
  13. #include <intuition/classusr.h>
  14. #include <intuition/imageclass.h>
  15. #include <intuition/cghooks.h>
  16. #include <intuition/icclass.h>
  17.  
  18. #include <graphics/gfxbase.h>
  19. #include <graphics/gfxmacros.h>
  20.  
  21. #include <utility/tagitem.h>
  22. #include <utility/hooks.h>
  23.  
  24. #include <clib/macros.h>
  25.  
  26. #ifdef _SASC
  27. #include <proto/exec.h>
  28. #include <proto/intuition.h>
  29. #include <proto/graphics.h>
  30. #include <proto/utility.h>
  31. #elif __GNUC__
  32. #include <clib/exec_protos.h>
  33. #include <clib/intuition_protos.h>
  34. #include <clib/graphics_protos.h>
  35. #include <clib/utility_protos.h>
  36. #endif
  37.  
  38. #ifdef _AROS
  39. #include <aros/asmcall.h>
  40. #include <clib/alib_protos.h>
  41. #include "intuition_intern.h"
  42. #endif
  43.  
  44. /****************************************************************************/
  45.  
  46. /* Some handy transparent base class object casting defines.
  47.  */
  48. #define G(o)  ((struct Gadget *)o)
  49. #define EG(o) ((struct ExtGadget *)o)
  50. #define IM(o) ((struct Image *)o)
  51.  
  52. /****************************************************************************/
  53.  
  54. /* FrameIClass specific instance data.
  55.  */
  56. struct FrameIData
  57. {
  58.     /* render bevel only with no fill? */
  59.     BOOL fid_EdgesOnly;
  60.  
  61.     /* inverted bevel pens? */
  62.     BOOL fid_Recessed;
  63.  
  64.     /* frame style? */
  65.     WORD fid_FrameType;
  66. };
  67.  
  68. /****************************************************************************/
  69.  
  70. #undef IntuitionBase
  71. #define IntuitionBase    ((struct IntuitionBase *)(cl->cl_UserData))
  72.  
  73. /* This is utility function used by frameiclass to draw a simple
  74.  * bevel.
  75.  */
  76. static void DrawFrame(
  77.     Class * cl,
  78.     struct RastPort *rport,
  79.     UWORD shine, UWORD shadow,
  80.     WORD left, WORD top, WORD width, WORD height,
  81.     BOOL thicken)
  82. {
  83.     /*
  84.     Here we attempt to render a bevel as quickly as possible using
  85.     as few system calls as possible. Note the ORDER of the rendering
  86.     and pen (or lack of) setting in important. This routine can be
  87.     useful alone as a basis for GadTools DrawBevelBox() perhaps, but
  88.     its real function is rendering the frameiclass components for the
  89.     various supported styles.
  90.  
  91.     It should be futher noted, on the native Amiga chipset, rendering
  92.     bevels via serious of RectFill()'s is potentially as much as two
  93.     times faster. However, in the case of AROS the implementation
  94.     of the graphics drivers would ofcourse be the determining factor.
  95.     Just as on the native OS, 3rd party gfx boards would be a factor.
  96.  
  97.     Additionally, if the frame metrics are changed here for whatever
  98.     reasons, you MUST also compensate the change in the frame class
  99.     render method, and framebox specifically the offset values.
  100.     */
  101.     height -= 1;
  102.     width  -= 1;
  103.  
  104.     /* Top/Left */
  105.     SetABPenDrMd(rport, shine, 0, JAM1);
  106.     Move(rport, left, top + height);
  107.     Draw(rport, left, top);
  108.     Draw(rport, left + width, top);
  109.  
  110.     /* Bottom/Right */
  111.     SetAPen(rport, shadow);
  112.     Draw(rport, left + width, top + height);
  113.     Draw(rport, left, top + height);
  114.  
  115.     if (thicken != FALSE)
  116.     {
  117.     /* Thicken Right Side */
  118.     Move(rport, left + width - 1, top + height - 1);
  119.     Draw(rport, left + width - 1, top + 1);
  120.  
  121.     /* Thicken Left Side */
  122.     SetAPen(rport, shine);
  123.     Move(rport, left + 1, top + height - 1);
  124.     Draw(rport, left + 1, top + 1);
  125.     } /* if */
  126. } /* DrawFrame */
  127.  
  128. /****************************************************************************/
  129.  
  130. /* frame render method */
  131. static ULONG draw_frameiclass(Class *cl, Object *o, struct impDraw *msg)
  132. {
  133.     struct FrameIData *fid = INST_DATA(cl, o);
  134.  
  135.     /*
  136.     Default pen array, this should be globally accessable from
  137.     all the boopsi objects, unless someone as a better idea...
  138.     */
  139.     UWORD default_pens[] =
  140.     {
  141.     1, /* detailPen      */
  142.     0, /* blockPen         */
  143.     1, /* textPen         */
  144.     2, /* shinePen         */
  145.     1, /* shadowPen      */
  146.     3, /* hiFillPen      */
  147.     1, /* hifilltextPen  */
  148.     0, /* backgroundPen  */
  149.     2  /* hilighttextPen */
  150.     };
  151.     ULONG retval;
  152.  
  153.     /* we will check the rastport present */
  154.     if(msg->imp_RPort != NULL)
  155.     {
  156.     UWORD *pens = default_pens;
  157.     UWORD loffset = 0, toffset = 0;
  158.     UWORD left, top;
  159.     UWORD shine, shadow;
  160.     BOOL selected;
  161.  
  162.     /* set up our rendering pens */
  163.     if (msg->imp_DrInfo)
  164.     {
  165.         /*
  166.         This test may not be necessary - and if that is the
  167.         case then this logic could be optimized a bit more.
  168.         */
  169.         if (msg->imp_DrInfo->dri_Pens)
  170.         {
  171.         pens = msg->imp_DrInfo->dri_Pens;
  172.         } /* if */
  173.  
  174.         /*
  175.         Fall back to mono color bevels if depth is only 1 bitplane.
  176.         */
  177.         if (msg->imp_DrInfo->dri_Depth == 1)
  178.         {
  179.         shine  = pens[SHADOWPEN];
  180.         }
  181.         else
  182.         {
  183.         shine  = pens[SHINEPEN];
  184.         } /* if */
  185.     }
  186.     else
  187.     {
  188.         shine  = pens[SHINEPEN];
  189.     } /* if */
  190.  
  191.     shadow    = pens[SHADOWPEN];
  192.  
  193.     switch(msg->imp_State)
  194.     {
  195.     case IDS_SELECTED:
  196.     case IDS_INACTIVESELECTED:
  197.         selected = TRUE;
  198.         break;
  199.  
  200.     default:
  201.         selected = FALSE;
  202.         break;
  203.     } /* switch */
  204.  
  205.     /*
  206.         I'm so clever :) We want to check if either of selected or
  207.         recessed is TRUE, and if so, swap the pens. However, if both
  208.         are true, they effectivly cancel each other out and we do
  209.         nothing. Rather than two compares against TRUE and a OR of the
  210.         results, pls the additional check to ignore the case where both
  211.         are TRUE, we will do an XOR of the bool's and check the result.
  212.         This should prove most efficient too.
  213.  
  214.  
  215.         Recess|select| XOR'd result
  216.         ------|------|-------
  217.           0   |  0     |  0
  218.         ------|------|-------
  219.           0   |  1     |  1
  220.         ------|------|-------
  221.           1   |  0     |  1
  222.         ------|------|-------
  223.           1   |  1     |  0
  224.         ------|------|-------
  225.     */
  226.  
  227.     if ( (fid->fid_Recessed ^ selected) != FALSE )
  228.     {
  229.         /* swap pens */
  230.         shine  ^= shadow;
  231.         shadow ^= shine;
  232.         shine  ^= shadow;
  233.     } /* if */
  234.  
  235.     left = IM(o)->LeftEdge + msg->imp_Offset.X;
  236.     top  = IM(o)->TopEdge  + msg->imp_Offset.Y;
  237.  
  238.     switch(fid->fid_FrameType)
  239.     {
  240.     case FRAME_DEFAULT:
  241.         toffset = 1;
  242.         loffset = 1;
  243.         DrawFrame(
  244.         cl,
  245.         msg->imp_RPort,
  246.         shine, shadow,
  247.         left, top,
  248.         IM(o)->Width, IM(o)->Height,
  249.         FALSE
  250.         );
  251.         break;
  252.  
  253.     case FRAME_BUTTON:
  254.         toffset = 1;
  255.         loffset = 2;
  256.         DrawFrame(
  257.         cl,
  258.         msg->imp_RPort,
  259.         shine, shadow,
  260.         left, top,
  261.         IM(o)->Width, IM(o)->Height,
  262.         TRUE
  263.         );
  264.         break;
  265.  
  266.     case FRAME_RIDGE:
  267.         toffset = 1;
  268.         loffset = 2;
  269.  
  270.         /* render outer pen-inverted thick bevel */
  271.         DrawFrame(
  272.         cl,
  273.         msg->imp_RPort,
  274.         shine, shadow,
  275.         left, top,
  276.         IM(o)->Width, IM(o)->Height,
  277.         TRUE
  278.         );
  279.  
  280.         /* render inner thick bevel */
  281.         DrawFrame(
  282.         cl,
  283.         msg->imp_RPort,
  284.         shadow, shine,
  285.         left + loffset, top + toffset,
  286.         IM(o)->Width - (loffset + loffset), IM(o)->Height - (toffset + toffset),
  287.         TRUE
  288.         );
  289.  
  290.         toffset += 1;
  291.         loffset += 2;
  292.         break;
  293.  
  294.     case FRAME_ICONDROPBOX:
  295.         toffset = 6;
  296.         loffset = 10;
  297.         /* not supported yet */
  298.         break;
  299.  
  300.     } /* switch */
  301.  
  302.     if(fid->fid_EdgesOnly == FALSE)
  303.     {
  304.         if(selected)
  305.         {
  306.         SetABPenDrMd(msg->imp_RPort, pens[FILLPEN], pens[BACKGROUNDPEN], JAM1);
  307.         }
  308.         else
  309.         {
  310.         SetABPenDrMd(msg->imp_RPort, pens[BACKGROUNDPEN], pens[BACKGROUNDPEN], JAM1);
  311.         } /* if */
  312.  
  313.         RectFill(msg->imp_RPort,
  314.         IM(o)->LeftEdge + loffset,
  315.         IM(o)->TopEdge  + toffset,
  316.         IM(o)->LeftEdge + IM(o)->Width  - (loffset+loffset),
  317.         IM(o)->TopEdge  + IM(o)->Height - (toffset+toffset)
  318.         );
  319.     } /* if */
  320.  
  321.     retval = 1UL;
  322.     }
  323.     else
  324.     {
  325.     /* return failure */
  326.     retval = 0UL;
  327.     } /* if */
  328.  
  329.     return retval;
  330. } /* draw_frameiclass */
  331.  
  332.  
  333. /****************************************************************************/
  334.  
  335. /* frame attribute setting method */
  336. static ULONG set_frameiclass(Class *cl, Object *o, struct opSet *msg)
  337. {
  338.     struct FrameIData *fid = INST_DATA(cl, o);
  339.  
  340.     struct TagItem *tstate = msg->ops_AttrList;
  341.     struct TagItem *tag;
  342.     ULONG retval = 0UL;
  343.  
  344.     while ((tag = NextTagItem(&tstate)))
  345.     {
  346.     switch(tag->ti_Tag)
  347.     {
  348.     case IA_Recessed:
  349.         fid->fid_Recessed    = (BOOL)( ( (BOOL)tag->ti_Data != FALSE ) ? TRUE : FALSE );
  350.         break;
  351.  
  352.     case IA_EdgesOnly:
  353.         fid->fid_EdgesOnly    = (BOOL)( ( (BOOL)tag->ti_Data != FALSE ) ? TRUE : FALSE );
  354.         break;
  355.  
  356.     case IA_FrameType:
  357.         /*
  358.         Data values for IA_FrameType (recognized by FrameIClass)
  359.  
  360.         FRAME_DEFAULT:    The standard V37-type frame, which has
  361.             thin edges.
  362.         FRAME_BUTTON:  Standard button gadget frames, having thicker
  363.             sides and edged corners.
  364.         FRAME_RIDGE:  A ridge such as used by standard string gadgets.
  365.             You can recess the ridge to get a groove image.
  366.         FRAME_ICONDROPBOX: A broad ridge which is the standard imagery
  367.             for areas in AppWindows where icons may be dropped.
  368.         */
  369.         fid->fid_FrameType = (WORD)tag->ti_Data;
  370.         break;
  371.  
  372.     } /* switch */
  373.     } /* while */
  374.  
  375.     return(retval);
  376. } /* set_frameiclass */
  377.  
  378. /****************************************************************************/
  379.  
  380. /* frameiclass framebox method */
  381. static ULONG framebox_frameiclass(Class *cl, Object *o, struct impFrameBox *msg)
  382. {
  383.     struct FrameIData *fid = INST_DATA(cl, o);
  384.  
  385.     if (msg->imp_FrameFlags & FRAMEF_SPECIFY)
  386.     {
  387.     /*
  388.         Would someone kindly explain RKM Libs page 898/899 in english :)
  389.         I'll just forget about this for the time being until I have
  390.         made more sence out of what is the "right thing" to do here.
  391.     */
  392.     }
  393.     else
  394.     {
  395.     switch(fid->fid_FrameType)
  396.     {
  397.     case FRAME_DEFAULT:
  398.         msg->imp_ContentsBox->Top     = msg->imp_FrameBox->Top    - 1;
  399.         msg->imp_ContentsBox->Left     = msg->imp_FrameBox->Left   - 1;
  400.         msg->imp_ContentsBox->Height = msg->imp_FrameBox->Height + 2;
  401.         msg->imp_ContentsBox->Width  = msg->imp_FrameBox->Width  + 2;
  402.         break;
  403.  
  404.     case FRAME_BUTTON:
  405.         msg->imp_ContentsBox->Top     = msg->imp_FrameBox->Top    - 1;
  406.         msg->imp_ContentsBox->Left     = msg->imp_FrameBox->Left   - 2;
  407.         msg->imp_ContentsBox->Height = msg->imp_FrameBox->Height + 2;
  408.         msg->imp_ContentsBox->Width  = msg->imp_FrameBox->Width  + 4;
  409.         break;
  410.  
  411.     case FRAME_RIDGE:
  412.         msg->imp_ContentsBox->Top     = msg->imp_FrameBox->Top    - 2;
  413.         msg->imp_ContentsBox->Left     = msg->imp_FrameBox->Left   - 4;
  414.         msg->imp_ContentsBox->Height = msg->imp_FrameBox->Height + 4;
  415.         msg->imp_ContentsBox->Width  = msg->imp_FrameBox->Width  + 8;
  416.         break;
  417.  
  418.     case FRAME_ICONDROPBOX:
  419.         msg->imp_ContentsBox->Top     = msg->imp_FrameBox->Top    - 6;
  420.         msg->imp_ContentsBox->Left     = msg->imp_FrameBox->Left   - 6;
  421.         msg->imp_ContentsBox->Height = msg->imp_FrameBox->Height + 12;
  422.         msg->imp_ContentsBox->Width  = msg->imp_FrameBox->Width  + 12;
  423.         break;
  424.     }
  425.     } /* if */
  426.  
  427.     return 1UL;
  428. } /* framebox_frameiclass */
  429.  
  430. /****************************************************************************/
  431.  
  432. /* frameiclass boopsi dispatcher
  433.  */
  434. AROS_UFH3(static IPTR, dispatch_frameiclass,
  435.     AROS_UFHA(Class *,  cl,  A0),
  436.     AROS_UFHA(Object *, o,   A2),
  437.     AROS_UFHA(Msg,      msg, A1)
  438. )
  439. {
  440.     IPTR retval = 0UL;
  441.  
  442.     switch(msg->MethodID)
  443.     {
  444.     case IM_FRAMEBOX:
  445.     retval = framebox_frameiclass(cl, o, (struct impFrameBox *)msg);
  446.     break;
  447.  
  448.     case IM_DRAWFRAME:
  449.     /* For this release, drawframe (wrongly) handled the same as... */
  450.  
  451.     case IM_DRAW:
  452.     retval = draw_frameiclass(cl, o, (struct impDraw *)msg);
  453.     break;
  454.  
  455.     case OM_SET:
  456.     retval = DoSuperMethodA(cl, o, msg);
  457.     retval += (IPTR)set_frameiclass(cl, o, (struct opSet *)msg);
  458.     break;
  459.  
  460.     case OM_NEW:
  461.     retval = DoSuperMethodA(cl, o, msg);
  462.     if (retval)
  463.     {
  464.         struct FrameIData *fid = INST_DATA(cl, retval);
  465.  
  466.         /* set some defaults */
  467.         fid->fid_EdgesOnly = TRUE;
  468.         fid->fid_Recessed  = FALSE;
  469.         fid->fid_FrameType = FRAME_DEFAULT;
  470.  
  471.         /* Handle our special tags - overrides defaults */
  472.         set_frameiclass(cl, (Object*)retval, (struct opSet *)msg);
  473.     }
  474.     break;
  475.  
  476.     default:
  477.     retval = DoSuperMethodA(cl, o, msg);
  478.     break;
  479.     } /* switch */
  480.  
  481.     return retval;
  482. }  /* dispatch_frameiclass */
  483.  
  484. #undef IntuitionBase
  485.  
  486. /****************************************************************************/
  487.  
  488. /* Initialize our image class. */
  489. struct IClass *InitFrameIClass (struct IntuitionBase * IntuitionBase)
  490. {
  491.     struct IClass *cl = NULL;
  492.  
  493.     /* This is the code to make the frameiclass...
  494.     */
  495.     if ((cl = MakeClass(FRAMEICLASS, IMAGECLASS, NULL, sizeof(struct FrameIData), 0)))
  496.     {
  497.     cl->cl_Dispatcher.h_Entry    = (APTR)AROS_ASMFUNC_NAME(dispatch_frameiclass);
  498.     cl->cl_Dispatcher.h_SubEntry = NULL;
  499.     cl->cl_UserData          = (IPTR)IntuitionBase;
  500.  
  501.     AddClass (cl);
  502.     }
  503.  
  504.     return (cl);
  505. }
  506.  
  507.